// util 是Node.js内部提供的很多实用或者工具类型的API，方便我们快速开发，非常多
const util = require('node:util')
const { exec } = require('node:child_process')
// exec('node -v', (err, stdout, stderr) => {

// })
// 通过util将exec函数转成 promise 格式   promisify （工具函数）
const execPromise = util.promisify(exec)   // 会返回一个新的函数
execPromise('node -v').then((res) => {       // 如果返回多个参数，res就是一个对象，如果返回一个参数，res就是最后结果
    console.log(res);   // { stdout: '', stderr: ''}
}).catch((err) => {
    console.log(err);
})
// promisify底层实现
/*
const promisify = (fn) => {        // 接收一个函数
    return (...args) => {      // 返回一个新的函数    参数要解构，可能多个
        return new Promise((resolve, reject) => {
            fn(...args, (err, ...values) => {   // 返回也可能多个
                if(err) {
                    reject(err)
                }
                if(values && values.length > 1) {
                    let obj = {}
                    for(let key in values) {
                        obj[key] = values[key]
                        resolve(obj)
                    }
                } else {
                    resolve(values[0])
                }
            })
        })
    }
}
*/
// 将Promise函数转换成 回调函数 的方式 callbackify
const func = (type) => {
    if(type == 1) {
        return Promise.resolve('success')
    } else {
        return Promise.reject('error')
    }
}

const callback = util.callbackify(func)
callback(1, (err, value) => {
    console.log(err, value);
})
// callbackify原理
/*
const callbackify = (fn) => {        // 接收一个函数
    return (...args) => {      // 返回一个新的函数    参数要解构，可能多个
        let callback = args.pop()          // 使用时，最后一个参数就是回调函数，这样拿到回调函数
        fn(...args).then(res => {
            callback(null, res)
        }).catch((err) => {
            callback(err)
        })
    }
}
*/

// util.format  格式化输出，跟c语言的 printf类似
console.log(util.format('%s---%s', 'xm', 'xx'));  // %s是匹配字符的，从第二个参数往后按顺序一一匹配， 最后输出 'xm---xx'
/*
util.format(format, [args])
    %s: String 将用于转换除 BigInt、Object 和 -0 之外的所有值。 
        BigInt 值将用 n 表示，没有用户定义的 toString 函数的对象使用具有选项 { depth: 0, colors: false, compact: 3 } 的 util.inspect() 进行检查。
    %d: Number 将用于转换除 BigInt 和 Symbol 之外的所有值。
    %i: parseInt(value, 10) 用于除 BigInt 和 Symbol 之外的所有值。
    %f: parseFloat(value) 用于除 Symbol 之外的所有值。
    %j: JSON。 如果参数包含循环引用，则替换为字符串 '[Circular]'。
    %o: Object. 具有通用 JavaScript 对象格式的对象的字符串表示形式。 类似于具有选项 { showHidden: true, showProxy: true } 的 util.inspect()。 这将显示完整的对象，包括不可枚举的属性和代理。
    %O: Object. 具有通用 JavaScript 对象格式的对象的字符串表示形式。 类似于没有选项的 util.inspect()。 这将显示完整的对象，但不包括不可枚举的属性和代理。
    %c: CSS. 此说明符被忽略，将跳过任何传入的 CSS。
    %%: 单个百分号 ('%')。 这不消费参数
如果不传入格式化参数 就按空格分开
    util.format(1,2,3)   // 1 2 3
*/
